package com.game.game.service.room;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.game.common.Transmitter;
import com.game.common.constants.GlobalConstants;
import com.game.core.constant.Constants.RoomRoundCount;
import com.game.core.net.common.RemoteNode;
import com.game.core.service.PublicService;
import com.game.core.service.ServiceContainer;
import com.game.game.service.server.ServerService;
import com.game.message.proto.room.RoomProtoBuf.BGRoomCreateRES;
import com.game.message.proto.room.RoomProtoBuf.GBForceRoomDestoryREQ;
import com.game.message.proto.room.RoomProtoBuf.GBRoomCreateREQ;
import com.game.message.proto.room.RoomProtoBuf.GWRoomCreateRES;
import com.game.message.proto.room.RoomProtoBuf.GWRoomQuitRES;
import com.game.message.proto.room.RoomProtoBuf.WGRoomCreateREQ;
import com.game.message.proto.room.RoomProtoBuf.WGRoomQuitREQ;
import com.game.message.protocol.ProtocolsConfig;

public class RoomService extends PublicService
{
	private static final long serialVersionUID = -95924175253120279L;
	private ConcurrentHashMap<Integer, RoomRoundCount> roomTypes = new ConcurrentHashMap<>(); // <Hoster accountID, RoomType>
	private ConcurrentHashMap<Integer, Integer> rooms = new ConcurrentHashMap<Integer, Integer>(); // <RoomId, ServerId>
	private ConcurrentHashMap<String, Integer> accountRooms = new ConcurrentHashMap<String, Integer>(); 
	private ConcurrentHashMap<String, Integer> tempQuitterRooms = new ConcurrentHashMap<String, Integer>();
	private final Logger logger = LoggerFactory.getLogger(RoomService.class);
	
	private Lock lock = new ReentrantLock();
	
	public int getRoomSize()
	{
		return rooms.size();
	}
	
	public Integer getRoom(String accountID)
	{
		return accountRooms.get(accountID);
	}
	
	private Integer getRoomServerID(Integer roomID)
	{
		if(roomID == null)
			return null;
		return rooms.get(roomID);
	}
	
	public RoomRoundCount getRoomRoundCount(int roomId)
	{
		return roomTypes.get(roomId);
	}
	
	/*
	 * 获得用户对应的Battle RemoteNode的
	 */
	public RemoteNode getBattleNode(String accountID)
	{
		ServerService serverService = ServiceContainer.getInstance().getPublicService(ServerService.class);
		Integer roomID = getRoom(accountID);
		Integer serverID = getRoomServerID(roomID);
		return serverService.getBattleNode(serverID);
	}
	
	public RemoteNode getBattleNode(Integer roomID)
	{
		ServerService serverService = ServiceContainer.getInstance().getPublicService(ServerService.class);
		Integer serverID = getRoomServerID(roomID);
		return serverService.getBattleNode(serverID);
	}
	
	/*
	 *  result. ( > 0 : 已拥有房间号 ; == 0 : 发往battle创建; -1 : 创建失败)
	 */
	public int createRoom(RemoteNode remoteNode, WGRoomCreateREQ message, int callback)
	{
		String accountID = message.getAccountID();
		GBRoomCreateREQ.Builder builder = GBRoomCreateREQ.newBuilder();
		ServerService service = ServiceContainer.getInstance().getPublicService(ServerService.class);
		RemoteNode battleNode = service.getRandomBattleNode();
		
		try
		{
			lock.lock();
			Integer roomID = accountRooms.get(accountID);
			if (roomID != null)
			{
				logger.error("Create Room Failed, already in room, accountID={}", accountID);
				GWRoomCreateRES.Builder msg = GWRoomCreateRES.newBuilder();
				msg.setAccountID(accountID);
				msg.setRoomID(roomID);
				msg.setResult(ProtocolsConfig.ROOM_CREATE_FAILED_ALREADY_IN_ROOM);
				Transmitter.getInstance().write(remoteNode, GlobalConstants.DEFAULT_CALLBACK, msg.build());
				return roomID;
			}
			
			RoomRoundCount roomRoundCount = RoomRoundCount.getValue(message.getType(), message.getCount());
			
			roomID = (int)((Math.random()*9+1) * 100000);
			while (rooms.get(roomID) != null)
				roomID = (int)((Math.random()*9+1) * 100000);
			rooms.put(roomID, battleNode.getServerID());
			accountRooms.put(accountID, roomID);
			builder.setAccountID(accountID);
			builder.setID(message.getID());
			builder.setCount(message.getCount());
			builder.setType(message.getType());
			builder.addAllRules(message.getRulesList());
			builder.setRoomID(roomID);
			builder.setServerID(remoteNode.getServerID());
			builder.setIp(message.getIp());
			roomTypes.put(roomID, roomRoundCount);
			Transmitter.getInstance().write(battleNode, GlobalConstants.DEFAULT_CALLBACK, builder.build());
			return roomID;
		}
		catch(Exception exception)
		{
			return -1;
		}
		finally
		{
			lock.unlock();
		}
	}
	
	public void createRoomResult(BGRoomCreateRES message, RemoteNode remoteNode)
	{
		GWRoomCreateRES.Builder builder = GWRoomCreateRES.newBuilder();
		builder.setResult(message.getResult());
		builder.setAccountID(message.getAccountID());
		builder.setRoomID(message.getRoomID());
		ServerService serverService = ServiceContainer.getInstance().getPublicService(ServerService.class);
		Transmitter.getInstance().write(serverService.getAccountNode(message.getAccountID()), GlobalConstants.DEFAULT_CALLBACK, builder.build());
	}
	
	
	private void roomQuitError(WGRoomQuitREQ message, int errorCode)
	{
		ServerService service = ServiceContainer.getInstance().getPublicService(ServerService.class);
		GWRoomQuitRES.Builder errorRes = GWRoomQuitRES.newBuilder();
		errorRes.setResult(errorCode);
		errorRes.setAccountID(message.getAccountID()); // 向申请加入房间的发消息。
		errorRes.setRoomID(message.getRoomID());
		errorRes.setQuitter(-1);
		errorRes.setQuitterAccountID(message.getAccountID());
		// 不设置ApplierAccountID，这个字段是通知别人 XXX进来了。
		Transmitter.getInstance().write(service.getAccountNode(message.getAccountID()), 
			GlobalConstants.DEFAULT_CALLBACK, errorRes.build());
	}
	
	

	//强制销毁房间，想bat服发送请求，等待bat推送
	public Boolean froceRoomDestroy(int id)
	{
		if(rooms.get(id) != null)
		{
			GBForceRoomDestoryREQ.Builder msg = GBForceRoomDestoryREQ.newBuilder();
			msg.setRoomID(id);
			ServerService service = ServiceContainer.getInstance().getPublicService(ServerService.class);
			Transmitter.getInstance().write(service.getBattleNode(rooms.get(id)), GlobalConstants.DEFAULT_CALLBACK, msg.build());
			return true;
		}
		else{
			logger.error("Destory room failed, not find room, roomID={} ", id);
			return false;
		}
	}

	
}